package com.conan.dailyflickr.activity;

import java.util.Calendar;
import java.util.Random;

import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.IBinder;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;
import android.widget.RemoteViews;

import com.conan.dailyflickr.R;
import com.conan.dailyflickr.app.BitmapManager_1;
import com.conan.dailyflickr.app.DailyFlickrApplication;
import com.conan.dailyflickr.app.DailyPrefernces;
import com.conan.dailyflickr.app.BitmapManager_1.ImageDownloadListener;
import com.conan.dailyflickr.app.DailyPrefernces.DailyInfo;
import com.conan.dailyflickr.app.PhotoDailyInfo;
import com.conan.dailyflickr.app.PhotoDailyInfo.Photo;
import com.conan.dailyflickr.app.PhotoDailyInfo.PhotoList;
import com.conan.dailyflickr.app.PhotoDailyInfo.PhotoSize;


/**
 * Background service to build any requested widget updates. Uses a single
 * background thread to walk through an update queue, querying
 * {@link WebserviceHelper} as needed to fill database. Also handles scheduling
 * of future updates, usually in 6-hour increments.
 */

public class UpdateService extends Service implements ImageDownloadListener{

	/**
	 * Interval to wait between background widget updates.
	 * Every 1 hours is plenty 
	 * to keep background data usage low and still provide fresh data
	 */
	private static final long UPDATE_INTERVAL = DateUtils.HOUR_IN_MILLIS;

	/** */
	private static final long UPDATE_THROTTLE = 30 * DateUtils.MINUTE_IN_MILLIS;

	public static final String ACTION_UPDATE_ALL = "com.handroid.dailyflickr.UPDATE_ALL";

	private int mAppWidgetId =  AppWidgetManager.INVALID_APPWIDGET_ID;
	private final String TAG = "[UpdateService]";
	// private PhotoDailyInfo mPhotoDaily;    
	private PhotoList mPhotoList;   
	private BitmapManager_1 mBmManager = new BitmapManager_1(this);

	public int mCountComplete = 0;
	public boolean mProcessingFlag = false;
	public boolean mLoadingFlag = false;
	private int[] imgViewArray ={
			R.id.img_0, R.id.img_1, R.id.img_2, R.id.img_3, R.id.img_4,
			R.id.img_5, R.id.img_6, R.id.img_7, R.id.img_8, R.id.img_9,
			R.id.img_10, R.id.img_11, R.id.img_12, R.id.img_13, R.id.img_14
	};
	
	final PhotoSize LARGE_SIZE = PhotoSize.SMALL;
	final PhotoSize SIZE = PhotoSize.SMALL_SQUARE;
	// int currentPage = 0;
	DailyInfo mInfo = null;
	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return null;
	}
	
	@Override
	public void completed(boolean largesize) {
		/*if(largesize) {
			String url = mPhotoList.get(mainId).getUrl(LARGE_SIZE);
			if(mBmManager.checkAvaiableBitmap(url)){
				mMainViewComplete = true;	
			}else{
				mBmManager.fetchMainBitmapOnThread(url);
			}
		}*/
		buildUpdate();
	}
	
	public void doownloadCompleted(){
		
	}
	
	public void notifyError(String message){
		DailyFlickrApplication.makeToastMessage(message);
	}
	
	public void buildUpdate(){
		if(!mProcessingFlag){
			mProcessingFlag = true;

			RemoteViews updateViews = new RemoteViews(getApplicationContext()
					.getPackageName(),  R.layout.flickr_widget);
			AppWidgetManager manager = AppWidgetManager.getInstance(UpdateService.this);
			
			
			String title = DailyFlickrWidget.STATUS; 
			for(int i = 0; i< mPhotoList.getCount(); i++){
				Photo photo = mPhotoList.get(i);

				// if(!photo.loaded){
				
				photo.loaded  = mBmManager.fetchAvaiableBitmap(photo.getUrl(SIZE), updateViews, imgViewArray[i]);
				
				// Log.i(PhotoDailyInfo.TAG, "[fetchAvaiableBitmap] ===== " +  photo.loaded);
				// }
				
				// update intent
				updateViews.setOnClickPendingIntent(
						imgViewArray[i],
						DailyFlickrWidget.makeSelectPendingIntent(getApplicationContext(), i, mAppWidgetId));
				
			}
			
			// update main photo view
			if(!TextUtils.isEmpty(mInfo._url)){
				if(mBmManager.checkAvaiableBitmap(mInfo._url)){
					mBmManager.fetchAvaiableBitmap(mInfo._url , updateViews, R.id.imv_main_img_of_dailyflickr_id);
					title = mInfo._title;
					updateViews.setOnClickPendingIntent(
							R.id.imv_main_img_of_dailyflickr_id,
							DailyFlickrWidget.makeMainSelectPendingIntent(getApplicationContext(),  mAppWidgetId));
				}else if(!mBmManager.checkAvaiableRequestBitmap(mInfo._url)){
					mBmManager.fetchBitmapOnThread(mInfo._url, -1);
				}
			}
			Log.e(PhotoDailyInfo.TAG, TAG + "[buildUpdate] = " + mBmManager.getSize());
			
			updateViews.setTextViewText(R.id.tv_main_message_text_id, title);
			manager.updateAppWidget(mAppWidgetId, updateViews);

			mProcessingFlag = false;
		}
	}
	
	// Main thread for running through any requested widget updates
	// also sets alarm to perform next update.
	public void fetchDataToUpdate(int page, String urlMainView) {
		mProcessingFlag = true;
		//  manager = AppWidgetManager.getInstance(this);

		if(mAppWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID && 
				DailyFlickrWidget.checkInternetConnection(getApplicationContext())){			
			// build update
			Log.i(PhotoDailyInfo.TAG, "-- fetchDataToUpdate( " + page + " ) --- " );
	        
			
			PhotoDailyInfo mPhotoDaily = new PhotoDailyInfo(getBaseContext());
			// clear cache
			// no need when use the soft reference
		    // mBmManager.clearRequestBitmap();
			
			// end clear cache			
			if(mPhotoDaily.updateDataFromFlickr(page, mInfo._date.getTime())){
				PhotoList temp = mPhotoDaily.getPhotoList();
				
				if(temp == null) return;

				// next day if go over the number pages of days
				if(temp.getCount() < 1 && 
						(mInfo._page > temp.getTotalPage())){
					mInfo._date.add(Calendar.DATE, 1);
					if(mPhotoDaily.updateDataFromFlickr(1, mInfo._date.getTime())){
						mInfo._page = 1;						
						DailyPrefernces.putPref(getApplicationContext(), mInfo._page, mInfo._date);
						
						temp = mPhotoDaily.getPhotoList();
					}else{
						mInfo._date.add(Calendar.DATE, -1);
					}
					
				}

				if(mPhotoList != null ){
					// clear old requests
					mBmManager.clearRequestBitmap();
					
					if(/*!mProcessingFlag &&*/ mPhotoList != null){
						for(int i = 0; i < mPhotoList.getCount(); i++){
							mBmManager.clearBitmapItem(mPhotoList.get(i).getUrl(SIZE));
						}
					}
				}
				
				mPhotoList = temp;
				
				// update status notify
				RemoteViews updateViews = new RemoteViews(getApplicationContext()
						.getPackageName(),  R.layout.flickr_widget);
				AppWidgetManager manager = AppWidgetManager.getInstance(UpdateService.this);
				updateViews.setTextViewText(R.id.tv_main_message_text_id, DailyFlickrWidget.STATUS);
		        updateViews.setTextViewText(R.id.tv_main_message_date_id, 
		        								DailyFlickrWidget.buildDateString(mInfo._date.getTime()) + 
		        								" - " + page);
		        manager.updateAppWidget(mAppWidgetId, updateViews);
				
				
				// fectch to dowload image update view
				for(int i = 0; i< mPhotoList.getCount(); i++){
					Photo photo = mPhotoList.get(i);
	
					mBmManager.fetchBitmapOnThread(photo.getUrl(SIZE), i);
				}
				
				if (TextUtils.isEmpty(urlMainView)){ 
					Random ran = new Random();
					
					Photo photo = mPhotoList.get(
										ran.nextInt(mPhotoList.getCount()));
					
					urlMainView = photo.getUrl(LARGE_SIZE);
					mBmManager.fetchBitmapOnThread(urlMainView, -1);
					
					DailyPrefernces.putPref(this, urlMainView, photo.getTitle());
				}
			
			}else{
				DailyFlickrApplication.makeToastMessage("Loading day - " 
						+ DailyFlickrWidget.buildDateString(mInfo._date.getTime()) + " - failed !!!");
				mInfo._date.add(Calendar.DATE, -1);
				// re-put date to reference
				DailyPrefernces.putPref(getApplicationContext(), -1, mInfo._date);
				mProcessingFlag = false;
				
				return;
			}
		}

		mProcessingFlag = false;
	}
	
	public void fetchDataToMainView(int page, int id) {		
		if(mPhotoList == null || mPhotoList.getCount() < 1) {
			fetchDataToUpdate(page, "new");
		}
		// invoke update view
		Photo photo = mPhotoList.get(id);
		String url = photo.getUrl(LARGE_SIZE);		
		
		DailyPrefernces.putPref(this, url, photo.getTitle());
		// clear all main view
		if(!TextUtils.isEmpty(mInfo._url)){
			mBmManager.clearBitmapItem(mInfo._url);
		}
		
		Log.i(PhotoDailyInfo.TAG, "[fetchDataToMainView] - " + mBmManager.checkAvaiableBitmap(url));
		mBmManager.fetchBitmapOnThread(url, -1);
		
		// update info
		mInfo._url = url;
		mInfo._title = photo.getTitle();
	}

	private void downloadImageToSaveOrSetBitmap(boolean isWallpaper){
		
	}
	@Override
	public void onCreate() {
		registerConectivityReceivers();
		super.onCreate();
	}

	/**
	 * start this service, creating a background processing thread
	 * if not already running. If started with {@link UpdateService#ACTION_UPDATE_ALL
	 * automatically add all widgets to the requested update queue
	 */
	@Override
	public void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);
		// http://www.vogella.de/articles/AndroidWidgets/article.html
		
		/** restart service unexpected*/
		mInfo = DailyPrefernces.getPref(this);
		if(intent == null) {
			fetchDataToUpdate(mInfo._page, mInfo._url);
		}else{			
			// kill service
			boolean stop = intent.getExtras().getBoolean("stop", false);
			if(stop){
				stopSelf();
				return;
			}			
			
			// download image
			if(intent.getExtras().getBoolean(DailyPrefernces.PREFS_NAME_URL, false)){
				boolean isWallpaper = intent.getExtras()
										.getBoolean(DailyPrefernces.PREFS_NAME_SET_WALLPAPER, false);
				downloadImageToSaveOrSetBitmap(isWallpaper);
				return;
			}
			// load data
			mAppWidgetId = intent.getExtras().getInt(
									AppWidgetManager.EXTRA_APPWIDGET_ID);
			int page = intent.getExtras().getInt(DailyPrefernces.PREFS_NAME_PAGE, -1);
			int id = intent.getExtras().getInt(DailyPrefernces.PREFS_NAME_MAIN_ID, -1);		
					
			Log.i(PhotoDailyInfo.TAG, "------- onStart() ------ " + page + " - " + id + mProcessingFlag);
			
			if(id >= 0){
				fetchDataToMainView(page, id);
				return;
			}else if(/*!mProcessingFlag && */ page >= 0){
				fetchDataToUpdate(page, mInfo._url);
			}
		}
	}

	
	
	private void registerConectivityReceivers() {
		if(mConnectivityReceiver == null){	
			mConnectivityReceiver = new ConnectivityReceiver();	
			this.registerReceiver(mConnectivityReceiver, new IntentFilter(
					ConnectivityManager.CONNECTIVITY_ACTION));
		}
	}

	private void unregisterConectivityReceivers() {
		if(mConnectivityReceiver != null){
			this.unregisterReceiver(mConnectivityReceiver);
			mConnectivityReceiver = null;
		}

	}
	
	  /** ConnectivityReceiver class */
	private ConnectivityReceiver mConnectivityReceiver;
    private class ConnectivityReceiver extends BroadcastReceiver {       

        @Override
        public void onReceive(final Context context, final Intent intent) {
            // Run the handler in MyExecutor to be protected by wake lock
           
            String action = intent.getAction();
            if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
                Bundle b = intent.getExtras();
                if (b != null) {
                    NetworkInfo netInfo = (NetworkInfo) b
                            .get(ConnectivityManager.EXTRA_NETWORK_INFO);
                    String type = netInfo.getTypeName();
                    NetworkInfo.State state = netInfo.getState();

                    NetworkInfo activeNetInfo = getActiveNetworkInfo();                  
                    
                    
                    if (state == NetworkInfo.State.CONNECTED) {
                    	mBmManager.changeConnectionInternet(true);
                    	mInfo = DailyPrefernces.getPref(getBaseContext());                    	
                    	fetchDataToUpdate(mInfo._page, mInfo._url);
                    } else if (state == NetworkInfo.State.DISCONNECTED) {
                    	mBmManager.changeConnectionInternet(false);
                      
                    }
                }
            }
        }

        private NetworkInfo getActiveNetworkInfo() {
            ConnectivityManager cm = (ConnectivityManager) getApplicationContext()
            								.getSystemService(Context.CONNECTIVITY_SERVICE);
            return cm.getActiveNetworkInfo();
        }
    }
    
	@Override
	public void onDestroy() {
		unregisterConectivityReceivers();
		mBmManager.killThread();		
		super.onDestroy();
	}

	@Override
	public void onLowMemory() {
		
		super.onLowMemory();
	}
	
	

}
